﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Tools.Base;

namespace LogicCenter.AssemblyPatch
{
    class MethodLoader
    {
        public Type tp = null;
        public MethodInfo method = null;
        public Object obj = null;
    }

    class AssemblyLoader : MarshalByRefObject
    {
        static AssemblyLoader()
        {

        }

        public void SetDomain(AppDomain arg_domain)
        {
            arg_domain.AssemblyResolve += CurrentDomain_AssemblyResolve;
        }

        private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
        {
            return null;
        }

        private Assembly assembly = null;

        // 方法表
        Dictionary<string, MethodLoader> dicMethodLoader = new Dictionary<string, MethodLoader>();

        public string FullName { get { return assembly.FullName; } }

        // 加载一个dll进来
        public bool LoadAssembly(string assemblyName)
        {
            try
            {
                try
                {
                    assembly = Assembly.Load(assemblyName);
                }
                catch(Exception ex)
                {
                    LogManager.WriteLog(string.Format("LoadAssembly 1 Failed. Msg={0}.", ex.Message), ex);
                }

                if(null == assembly)
                {
                    var list = Directory.EnumerateFiles(Directory.GetCurrentDirectory(), assemblyName + ".dll");
                    foreach(var path in list)
                    {
                        try
                        {
                            assembly = Assembly.LoadFile(path);
                            if(null == assembly)
                            {
                                continue;
                            }
                            else if(string.Compare(assemblyName, assembly.GetName().Name, true) != 0)
                            {
                                continue;
                            }

                            break;
                        }
                        catch(Exception ex)
                        {
                            LogManager.WriteLog(string.Format("LoadAssembly 2 Failed. Msg={0}.", ex.Message), ex);
                        }
                    }
                }

                if(null == assembly)
                {
                    // 如果名字不一致，则不接受。
                    //assembly = assembly;
                }
            }
            catch(Exception ex)
            {
                LogManager.WriteLog(string.Format("LoadAssembly 3 Failed. Msg={0}.", ex.Message), ex);
            }

            return null != assembly;
        }

        public MethodLoader FindMethod(string fullClassName, string methodName)
        {
            MethodLoader methodLoader = null;
            string strKey = string.Format("{0}.{1}", fullClassName, methodName);
            if(dicMethodLoader.TryGetValue(strKey, out methodLoader))
            {
                return methodLoader;
            }

            return null;
        }

        public void AddMethod(string fullClassName, string methodName, MethodLoader methodLoader)
        {
            try
            {
                string strKey = string.Format("{0}.{1}", fullClassName, methodName);
                dicMethodLoader.Add(strKey, methodLoader);
            }
            catch(Exception ex)
            {
                LogManager.WriteLog(string.Format("AddMethod Failed. Msg={0}.", ex.Message), ex);
            }
        }

        public bool LoadMethod(string fullClassName, string methodName)
        {
            try
            {
                MethodLoader methodLoader = FindMethod(fullClassName, methodName);
                // 找到了现有的
                if(null != methodLoader)
                {
                    return true;
                }
                methodLoader = new MethodLoader();
                methodLoader.tp = assembly.GetType(fullClassName);
                if(null == methodLoader.tp)
                {
                    return false;
                }

                methodLoader.method = methodLoader.tp.GetMethod(methodName);
                if(null == methodLoader.method)
                {
                    return false;
                }

                methodLoader.obj = Activator.CreateInstance(methodLoader.tp);
                if(null == methodLoader.obj)
                {
                    return false;
                }

                // 加载后马上添加进运行列表中
                AddMethod(fullClassName, methodName, methodLoader);
            }
            catch(Exception ex)
            {
                LogManager.WriteLog(string.Format("LoadMethod Failed. Msg={0}.", ex.Message), ex);
                return false;
            }

            return true;
        }

        public object Invoke(string fullClassName, string methodName, object[] args)
        {
            MethodLoader methodLoader = null;
            string strKey = string.Format("{0}.{1}", fullClassName, methodName);
            if(!dicMethodLoader.TryGetValue(strKey, out methodLoader))
            {
                return null;
            }

            return methodLoader.method.Invoke(methodLoader.obj, args);
        }
    }
}
